package tp.pr5.mv.instructions.mem;

import tp.pr5.mv.Instruction;
import tp.pr5.mv.Memory;
import tp.pr5.mv.Opcode;
import tp.pr5.mv.OperandStack;
import tp.pr5.mv.ProgramCounter;
import tp.pr5.mv.inout.InMethod;
import tp.pr5.mv.inout.OutMethod;
import tp.pr5.mv.instructions.OneParamInstructions;
import tp.pr5.mv.traps.IncorrectDirEx;
import tp.pr5.mv.traps.MVTrap;
import tp.pr5.mv.traps.WithoutOperandsEx;

public class STORE extends OneParamInstructions {

	
	public STORE() { // Constructor por defecto
		n = 0;
		op = Opcode.STORE;
	}
	
	public STORE(int par) { // Constructor con un parámetro
		n = par; // Asignamos al atributo protegido n el valor de par
		op = Opcode.STORE;
	}
	
	public void execute(OperandStack stack, Memory mem, ProgramCounter pc, InMethod inMethod, OutMethod outMethod) throws MVTrap {

		if ( stack.isEmpty() )     // Necesitamos al menos un operando en la pila.
			throw new WithoutOperandsEx( this, stack.getCounter() );
		
				
		int a = stack.top(); // Cogemos la cima de la pila
		
		if ( !mem.write(n, a))    // Si no podemos escibir en la posición es que es incorrecta (negativa).
			throw new IncorrectDirEx ( this, n );	 
			
			
		stack.pop();        // Sólo se quita el valor de la cima si ha tenido éxito la escritura

	}
	
	public Instruction create(int par) { // Devolvemos una instrucción store con un determinado parámetro
		
		return new STORE(par);
		
	}


	
	
}
